home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / UTILREEN / LJBOOK22.LZH / LJBOOK22.ASM < prev    next >
Assembly Source File  |  1988-12-15  |  29KB  |  1,080 lines

  1.     page    74,132
  2.     title    ljbook - print files 2-up 2-sided on hp ljp
  3. ;
  4. ; LJBOOK (c) Copyright 1987-1988 Vernon D. Buerg. ALL RIGHTS RESERVED.
  5. ; For private, personal use only. May not be sold or bundled.
  6. ;
  7. ; syntax:    ljbook    filename  [outfile]  [/f] [/p] [/d] [/2] [/t...]
  8. ;
  9. ; v0.90 7/02/87 - first flyer
  10. ; v0.97 7/05/87 - add option switches
  11. ; v0.98 7/19/87 - correction for multiples of 4 pages
  12. ; v0.99 8/10/87 - correction for files over 256 pages
  13. ; v1.0 10/05/87 - first public release
  14. ; v1.01 11/22/87 - play with line length and margins
  15. ; v1.02 1/14/88 - some suggestions from Guy Gallo
  16. ;        - print only one sheet if 1 or 2 pages
  17. ;        - leave empty pages blank
  18. ; v1.03 1/15/88 - process tabs
  19. ; v1.04, 1/26/88 - add /T title option
  20. ; v1.05, 1/26/88 - add /2 option
  21. ; v1.06, 2/05/88 - correct tab spacing
  22. ; v2.00, 2/10/88 - make MS-MASM v5 compatible
  23. ; v2.10, 4/04/88 - incorporate RWS mods for BOLD18.USL downloadable font
  24. ;           by R. W. Smetana
  25. ; v2.20,10/28/88 - change symbol set for use with Laserjet series II    ;220
  26. ;
  27.  
  28. cpl    equ    83            ; characters per line        ;101
  29.  
  30.  
  31. display macro    txt
  32.     mov    dx,offset txt        ; offset to message
  33.     call    prints            ; display it
  34.     endm
  35.  
  36.  
  37. send    macro    txt,len         ; send string to printer
  38.     mov    dx,offset txt        ; initialization codes
  39.     mov    cx,len            ; length of start-of-page codes
  40.     mov    bx,ohandle        ; write to output file
  41.     mov    ah,40h            ; write to file
  42.     int    21h            ;
  43.     endm
  44.  
  45.  
  46.  
  47. ;        psp data area structures
  48.  
  49. psp        struc            ; program segment prefix
  50. psp_int_20    db    0cdh,020h    ; int 20 instruction
  51. psp_top     dw    ?        ; top of memory in paragraph form
  52. psp_resvl    dw    ?        ; reserved
  53. psp_bytes    dw    ?,?        ; bytes available in segment
  54.         db    118 dup (?)    ; unused
  55. psp_parm_len    db    ?        ; characters in parameter list
  56. psp_parms    db    127 dup (?)    ; command parameters
  57. psp        ends
  58.  
  59.  
  60. cseg    segment public para 'code'
  61.     assume cs:cseg, ds:cseg, es:cseg
  62.     org    100h
  63.  
  64. ljbook    proc    far
  65.     lea    sp,word ptr lstack    ; set local stack
  66.     call    chkver            ; check dos version
  67.     call    parms            ; process command line
  68.     call    alloc            ; allocate buffers
  69.     call    open            ; access input file
  70.     call    scan            ; build page table
  71.     call    headers         ; set up (optional) headings
  72.     call    copy            ; print file
  73.     call    close            ; release input file
  74.     mov    byte ptr errlvl,0    ; set good return code
  75.     jmp    short exit        ; and return to system
  76.  
  77. error1:
  78.     mov    dx,offset usage     ; show syntax
  79. error:
  80.     mov    ax,cs            ; insure local regs
  81.     mov    ds,ax            ;
  82.     mov    es,ax            ;
  83.     lea    sp,word ptr lstack    ; insure stck pt
  84.     mov    byte ptr errlvl,1    ; set bad return
  85.     call    prints            ; print error message
  86. exit:
  87.     display null            ; space last line
  88.     mov    al,byte ptr errlvl    ; get error level
  89.     mov    ah,4ch            ; set exit function
  90.     int    21h            ; return to dos
  91.  
  92.     page
  93. ;
  94. ;    equates, constants, and data areas
  95.  
  96. tab    equ    09h            ; tabby
  97. lf    equ    0ah            ; line-feed
  98. ff    equ    0ch            ; form-feed
  99. cr    equ    0dh            ; carriage return
  100. eof    equ    1ah            ; end-of-file
  101. blank    equ    20h            ; space
  102.  
  103. prn        equ    4        ; handle for standard printer
  104. switch_char    equ    '/'             ; delimiter for command line switches
  105. stopper     equ    255        ; ends text strings
  106.  
  107. version db    cr,lf,'LJBOOK  (c) Copyright 1987-88 by Vernon D. Buerg'
  108.     db    cr,lf,'Version 2.2. For personal use only. May not be sold.',stopper    ;220
  109. usage    db    cr,lf
  110.     db    cr,lf,'Usage:'
  111.     db    cr,lf,'       ljbook  filename  [outfile] '             ;210
  112.     db              '[/f][/p][/d][/2][/B][/t...]'             ;210
  113.     db    cr,lf
  114.     db    cr,lf,'       /f       put filename in heading of each page'
  115.     db    cr,lf,'       /p       put page number in heading'
  116.     db    cr,lf,"       /d       put today's date/time in heading"
  117.     db    cr,lf,'       /2       one sided, two up printing'
  118.     db    cr,lf,'       /B       use BOLD18.USL font'             ;210
  119.     db    cr,lf,"       /ttext   put 'text' in heading"
  120. null    db    cr,lf,stopper,26
  121.  
  122. flags    db    0            ; procesing options
  123.  swf    equ    1            ; /f = filename in heading
  124.  swd    equ    2            ; /d = put today's date/time in heading
  125.  swp    equ    4            ; /p = put page numbers in heading
  126.  swt    equ    16            ; /t = title supplied
  127.  sw2    equ    32            ; /2 = one sided, two up
  128.  rws    equ    64            ; /B = use BOLD18.USL font    ;210
  129.  
  130. errlvl    db    0            ; dos error level returned
  131. lastchr db    0            ; previously read char
  132.  
  133. max    dw    0            ; maximum pages/table entries
  134. min    dw    128            ; minimum
  135.  
  136. right_table    dw    offset table    ; offset to next right side entry
  137. left_table    dw    offset table    ; offset for left side
  138.  
  139. pages    dw    1            ; number of pages
  140. sides    dw    0            ; number of two-up pages
  141. sheets    dw    0            ; number of sheets
  142.  
  143. round_up    dw    3        ; to make
  144. round_mask    dw    0FFFCh        ;   multiple of 4 or 2
  145.  
  146. lpp    equ    66            ; lines per page
  147. lcnt    dw    0            ; current lines on page
  148. linelen dw    0            ; length of current line
  149.  
  150. filepos dw    0,0            ; current file offset
  151.  
  152. ibuf    dw    offset table        ; next input character
  153. ilen    dw    0            ; bytes in buffer
  154. ihandle dw    0            ; input handle
  155. msgopni db    cr,lf,"Can't open input file - "
  156. ifile    db    76 dup (0),255        ; input file name
  157.  
  158. ohandle dw    prn            ; output handle
  159. msgopno db    cr,lf,"Can't open output file - "
  160. ofile    db    76 dup (0),255        ; output file name
  161.  
  162.     page
  163. ;
  164. ;    print command codes
  165.  
  166. init    label    byte            ; initialization strings    ;102
  167.     db    027,'&l1O'              ; landscape                     ;200
  168.     db    027,'(10U'              ; PC symbol set 1, Y cart       ;220
  169.     db    027,'&l8d'              ; 8 lpi                         ;099
  170.     db         '1e'               ; top margin                    ;099
  171.     db         '67f'              ; text length, 8x8.5=68 lines   ;099
  172.     db         '5.5C'             ; vertical motion index = n/48  ;099
  173. initlen equ    $-init            ;
  174.  
  175. initrws label    byte            ; additional for BOLD18.USL    ;210
  176.     db    027,'(s0p'              ; fixed spacing                 ;200
  177.     db         '1C'               ; disable line wrap             ;101
  178.     db    027,'(1X'               ; invoked as dl font #1         ;210
  179. initrwslen equ    $-initrws        ;
  180.  
  181.  
  182. initljp label    byte            ; additional for LJP        ;210
  183.     db    027,'(s0p'              ; fixed spacing                 ;200
  184.     db         '16.66h'           ; font pitch \ see k2s          ;099
  185.     db         '8.5v'             ; point size /                  ;099
  186.     db         '0d'               ; style                         ;099
  187.     db         '0b'               ; weight                        ;099
  188.     db         '0t'               ; typeface                      ;099
  189.     db         '1C'               ; disable line wrap             ;101
  190. initljplen equ    $-initljp        ;                ;210
  191.  
  192.  
  193.     page
  194. ;
  195. ;    control codes for left and right side set-up
  196.  
  197.                     ; printer codes for left side
  198. left_side    db    27,'9';cr       ;  clear margins
  199.         db    27,'&a1r'       ;  line 1                       ;099
  200.         db        'a'         ;  left margin                  ;099
  201. lmargl        db         '01la'     ;                               ;210
  202. lmargr        db         '89M'      ;  right margin                 ;210
  203.         db    cr        ;  column 0
  204. left_side_len    equ    $-left_side
  205.  
  206.                     ; printer codes for right side
  207. right_side    db    27,'9';cr       ;  clear margins
  208.         db    27,'&a1r'       ;  line 1                       ;099
  209. rmargl        db         '096l'     ;  left margin                  ;210
  210. rmargr        db         '178M'     ;  right margin                 ;210
  211.         db    cr        ;  column 96 (col 1)
  212. right_side_len    equ    $-right_side
  213.  
  214. endpage db    ff            ; printer codes to write at end of page
  215. endlen    equ    $-endpage
  216.  
  217. reset    db    027,'E'                 ; reset printer
  218. resetln equ    $-reset
  219.  
  220.     page
  221. ;
  222. ;    messages
  223.  
  224. info    db    cr,lf,lf
  225. infonr    db    '       sheets to print.',stopper
  226.  
  227. side1    db    cr,lf,cr,lf,'Printing side 1 ...',stopper
  228. side2    db    cr,lf,cr,lf,'Printing side 2 ...',stopper
  229.  
  230. prompt    db    cr,   'Side 1 printed.    ',cr,lf
  231.     db    cr,lf,'Place printed paper back in paper tray, '
  232.     db    cr,lf,'and press ENTER when ready ...',stopper
  233.  
  234. ended    db    cr,   'Finished printing. ',cr,lf,stopper
  235.  
  236. msgmem    db    cr,lf,'Insufficient memory',255
  237. msgver    db    cr,lf,'Incorrect DOS version',255
  238. msgread db    cr,lf,'Error reading file',255
  239.  
  240.     page
  241. ;
  242. ;    page headings and titles
  243.  
  244. page_const    db    'Page '
  245.  
  246. lheader     db    cr        ; line 1 of left page
  247. left_page    equ    $        ; spot for 'Page'
  248. left_pagenr    equ    $+4        ; spot for page number
  249. left_date    equ    lheader+18    ; spot for date
  250. left_time    equ    lheader+35    ; spot for time
  251.         db    80 dup (' ')    ; supplied title
  252. left_fname    equ    $-1        ; last char of leftmost filename
  253.         db    cr,lf,lf    ; blank line 2
  254. lheader_len    equ    $-lheader    ; length of titles
  255.  
  256. rheader     db    cr        ; line 1 of right page
  257. right_fname    equ    $        ; first char of rightmost filename
  258.         db    80 dup (' ')    ; supplied title
  259. right_page    equ    $-4-6        ; spot for 'Page'
  260. right_pagenr    equ    $-6        ; spot for page number
  261. right_time    equ    right_page-12    ; spot for time
  262. right_date    equ    right_time-17
  263.         db    cr,lf,lf    ; blank line 2
  264. rheader_len    equ    $-rheader
  265.  
  266. months    db    ' Jan Feb Mar Apr MayJuneJuly Aug Sep Oct Nov Dec'
  267.  
  268.     page
  269. ;
  270. ;    check dos version
  271.  
  272. chkver    proc    near
  273.     display version         ; display verion number
  274.     mov    ah,30h            ; get dos version
  275.     int    21h            ;
  276.     cmp    al,2            ; at least 2.0?
  277.     jae    chkdver         ;  yes, good
  278.     mov    dx,offset msgver    ;  no, complain
  279.     jmp    error            ;   and exit
  280. chkdver:                ;
  281.     ret                ; resume
  282. chkver    endp                ;
  283.  
  284.     page
  285. ;
  286. ;    parse command line
  287.  
  288. parms    proc    near
  289.     mov    si,psp_parm_len     ; point to command line       ;200
  290.     sub    cx,cx            ; to receive command line length
  291.     lodsb                ;
  292.     or    cl,al            ; any command line?
  293.     jnz    switches        ; yes, continue
  294.     jmp    error1            ; no, show usage
  295.  
  296. switches:
  297.     mov    di,psp_parms        ; offset to command parameters    ;200
  298. switches0:
  299.     mov    al,switch_char        ; see if ANY switches
  300.     repne    scasb            ;
  301.     je    switch3         ;
  302. switch2:jmp    switched        ; none, skip next
  303.  
  304. switch3:
  305.     jcxz    switch2         ; no more data
  306.     mov    byte ptr -1[di],cr    ; terminate command line at first /
  307.     cmp    byte ptr -2[di],blank    ;
  308.     jne    switchesa        ;
  309.     mov    byte ptr -2[di],cr    ;
  310. switchesa:
  311.     mov    si,di            ; point to next char
  312.     lodsb                ; get char following switch char
  313.     cmp    al,'a'                  ;  and make it upper case
  314.     jb    switches1        ;
  315.     sub    al,blank        ;
  316. switches1:
  317.     cmp    al,'F'                  ; show file name?
  318.     jne    switches2        ;
  319.     or    flags, swf        ;
  320. switches2:
  321.     cmp    al,'D'                  ; show date/time?
  322.     jne    switches3        ;
  323.     or    flags, swd        ;
  324. switches3:
  325.     cmp    al,'P'                  ; create page numbers?
  326.     jne    switches4        ;
  327.     or    flags, swp        ;
  328.  
  329. switches4:
  330.     cmp    al,'T'                  ; add user title?
  331.     jne    switches6        ; nope, all done here
  332.     sub    cx,1            ; less the switch and ending cr
  333.     jle    switches6        ; oops, t'aint none
  334.     cmp    cx,40            ; too long?
  335.     jbe    switches5a        ; no, it will fit
  336.     mov    cx,40            ;
  337. switches5a:
  338.     push    cx            ; save remaining length
  339.     mov    di,offset right_fname    ;
  340.     rep    movsb            ; overlay filename with title
  341.     pop    cx            ; get length back
  342.     dec    si            ; point to last char
  343.     mov    di,offset left_fname    ; left side is backwards
  344.     std                ;
  345.     rep    movsb            ;
  346.     cld                ; back to normal direction
  347.     or    flags, swt        ; we have titles
  348.     and    flags, 255-swf        ; can't have both
  349.  
  350. switches6:
  351.     cmp    al,'2'                  ; one sided, two up?
  352.     jne    switches7        ;
  353.     or    flags, sw2        ;
  354.     mov    round_up,1        ; reset round up factors
  355.     mov    round_mask,0FFFEh    ;
  356.  
  357. switches7:
  358.     cmp    al,'B'                  ; using BOLD18.USL font?        ;210
  359.     jne    switches8        ;                ;210
  360.     or    flags, rws        ; credit where credit is due    ;210
  361.  
  362. switches8:
  363.     jcxz    switched        ; any more operands?
  364.     jmp    switches0        ; yup
  365.  
  366. switched:
  367.  
  368.     page
  369. ;
  370. ;    get file names for input and output (printer) files
  371.  
  372. parm0:
  373.     mov    si,psp_parms        ; point to command line again    ;200
  374.     sub    ch,ch            ;
  375.     mov    cl,byte ptr ds:[psp_parm_len] ; get length back
  376. parm1:
  377.     lodsb                ; next char
  378.     cmp    al,blank        ; skip leading blanks
  379.     je    parm1a            ;
  380.     cmp    al,tab            ; skip tabs, too
  381.     jne    parm2            ;
  382. parm1a: loop    parm1            ;
  383.     jmp    error1            ; operand(s) missing
  384.  
  385. parm2:
  386.     mov    di,offset ifile     ; target for input file name
  387.     sub    cx,1            ; account for last lodsb
  388.     jge    parm3            ; if more to process
  389.     jmp    error1            ; operand(s) missing
  390. parm3:
  391.     stosb                ; previous char
  392.     lodsb                ; next char
  393.     cmp    al,blank        ; have operand separator?
  394.     jbe    parm4            ; yes, have first op
  395.     loop    parm3            ;
  396.     stosb                ;
  397.     jmp    short parm8        ; no second operand, use printer
  398.  
  399. parm4:
  400.     mov    di,offset ofile     ; target for output file name
  401.     jcxz    parm8            ; if no second operand
  402. parm5:
  403.     lodsb                ; skip intervening delimiters
  404.     cmp    al,blank        ;
  405.     je    parm6            ;
  406.     cmp    al,cr            ; end of parameters?
  407.     je    parm8            ; yes, just one operand
  408.     cmp    al,tab            ; skip tabs
  409.     jne    parm7            ;
  410. parm6:    loop    parm5            ; until no more command parameters
  411.     jmp    short parm8        ; none left
  412.  
  413. parm7:                    ; copy 2nd parm to output file name
  414.     stosb                ; its first/next char
  415.     lodsb                ; get next command line char
  416.     cmp    al,cr            ; end of it?
  417.     jbe    parm8            ; yes, have both operands now
  418.     loop    parm7            ;
  419. parm8:    ret                ;
  420. parms    endp
  421.  
  422.     page
  423. ;
  424. ;    allocate memory and buffer(s)
  425.  
  426. alloc    proc   near
  427.     mov    ax,word ptr ds:psp_bytes ;size of segment
  428.     sub    ax,pgmsize        ; less program size
  429.     sub    dx,dx            ;
  430.     mov    cx,ltable        ; size of each table entry
  431.     div    cx            ;  to get maximum entries
  432.     mov    max,ax            ;
  433.     cmp    ax,min            ; have enough?
  434.     jb    alloc_err        ; no,
  435.     mov    cx,ax            ; clear table
  436.     mov    di,offset table     ;
  437.     sub    ax,ax            ; to zeros
  438. alloc1:
  439.     stosw                ;
  440.     stosw                ;
  441.     stosw                ;
  442.     loop    alloc1            ;
  443.     ret
  444.  
  445. alloc_err:
  446.     mov    dx,offset msgmem    ; insufficient memory
  447.     jmp    error            ; return and exit
  448. alloc    endp
  449.  
  450. open    proc    near
  451.     mov    dx,offset ifile     ; input file name
  452.     mov    ax,3d00h        ; for input
  453.     int    21h            ;
  454.     jc    open_err1        ;
  455.     mov    word ptr ihandle,ax    ; save input file handle
  456.  
  457.     cmp    byte ptr ofile,0    ; was output file specified?
  458.     je    open_exit        ; no, use default printer
  459.     mov    dx,offset ofile     ; output file name
  460.     mov    ah,3ch            ;  for create
  461.     sub    cx,cx            ; normal attribute
  462.     int    21h            ;
  463.     jc    open_err2        ; failed
  464.     mov    ohandle,ax        ; save new output handle
  465. open_exit:
  466.     ret                ;
  467.  
  468. open_err1:
  469.     mov    dx,offset msgopni    ; input failed to open
  470.     jmp    error            ; return and exit
  471.  
  472. open_err2:
  473.     mov    dx,offset msgopno    ; output failed to open
  474.     jmp    error            ; return and exit
  475. open    endp
  476.     page
  477. ;
  478. ;    close all files
  479.  
  480. close    proc    near            ; close input and output files
  481.     mov    bx,word ptr ihandle    ; get input handle
  482.     or    bx,bx            ; was it opened?
  483.     jz    close2            ; no, skip it
  484.     mov    ah,3eh            ; yes, close it
  485.     int    21h            ;
  486.     mov    word ptr ihandle,0    ; mark it closed
  487. close2:
  488.     mov    bx,word ptr ohandle    ; get output handle
  489.     cmp    bx,prn            ; is it standard printer?
  490.     jbe    closed            ; yes, skip it
  491.     mov    ah,3eh            ; yes, close it
  492.     int    21h            ;
  493.     mov    word ptr ohandle,0    ; mark it closed
  494. closed:
  495.     ret                ; resume
  496. close    endp
  497.  
  498.     page
  499. ;
  500. ;    Print string like int 21h function 9
  501.  
  502. prints    proc    near            ; dx has offset to string
  503.     push    di            ;  ending in char x'ff'
  504.     push    bx            ;
  505.     push    cx            ;
  506.     mov    di,dx            ; ptr to string text
  507.     mov    cx,-1            ; overall text length
  508.     mov    al,255            ; find ending hex ff
  509.     repne    scasb            ;
  510.     not    cx            ; length is bytes scanned
  511.     mov    bx,1            ; standard output device
  512.     mov    ah,40h            ; write to a file or handle
  513.     int    21h            ;
  514.     pop    cx            ; recover registers
  515.     pop    bx            ;
  516.     pop    di            ;
  517.     ret                ;
  518. prints    endp
  519.  
  520.     page
  521. ;
  522. ;    scan input file for page markers
  523.  
  524. scan    proc    near
  525.     mov    bx,right_table        ; pointer to table entry
  526.     mov    al,0            ; no history
  527. scanread:
  528.     mov    byte ptr lastchr,al    ; save previous character
  529.     call    getc            ; get next char
  530.     jc    scanned         ; all done
  531.     inc    word ptr [bx]        ; bump page size
  532.     cmp    al,027            ; is it control char?        ;200
  533.     jbe    scan0            ; yes, don't bump line length
  534.     inc    word ptr linelen    ; bump line length
  535. scan0:
  536.     cmp    word ptr linelen,cpl    ; reached line limit?
  537.     ja    scan1            ; yes, force new line
  538.     cmp    al,lf            ; new line?
  539.     jne    scan2            ; no,
  540. scan1:
  541.     inc    lcnt            ; yes, bump line count
  542.     mov    word ptr linelen,0    ; reset line length
  543.     cmp    lcnt,lpp        ; reached end of page?
  544.     jb    scanread        ; no, continue
  545.     jmp    short scan3        ; yes, simulate end of page
  546. scan2:
  547.     cmp    al,ff            ; found start of next page?
  548. ;102    jne    scanread        ; no, keep reading
  549.     je    scan3            ; yes, check for full page
  550.     cmp    al,tab            ; is it a tabby?
  551.     jne    scanread        ; no, read some more
  552.     add    linelen,7        ; yes, bump to
  553.     and    linelen,0fff8h        ;  next tab column
  554.     jmp    scanread        ;   and continue reading
  555. scan3:
  556.     cmp    lcnt,0            ; any lines yet?
  557.     jne    scan4            ; yes, have lines to print
  558.     cmp    lastchr,lf        ; no, but was previous an lf?
  559.     je    scanread        ; yes, already have page boundary
  560. scan4:
  561.     inc    pages            ; bump page count
  562.     mov    lcnt,0            ; reset line counter
  563.     add    bx,ltable        ; point to next table entry
  564.     mov    right_table,bx        ;
  565.     mov    di,filepos        ; get
  566.     mov    dx,filepos+2        ;  file
  567.     mov    word ptr 2[bx],di    ;   position
  568.     mov    word ptr 4[bx],dx    ;    for next page
  569.     jmp    short scanread        ; look for next page
  570.  
  571. scanned:
  572.     ret                ; done, return
  573. scan    endp
  574.  
  575.     page
  576. ;
  577. ;    get next byte from read buffer
  578.  
  579.  
  580. getc    proc    near
  581.     sub    ilen,1            ; decr byte count
  582.     jl    getb            ; no more, get next block
  583.     mov    si,word ptr ibuf    ; next input char
  584.     lodsb                ; get next char
  585.     mov    word ptr ibuf,si    ;
  586.     mov    byte ptr lastchr,al    ; save previous character
  587.     cmp    al,eof            ; logical end of file?
  588.     je    getcx            ; yes, set return
  589.     add    filepos,1        ; bump file position
  590.     adc    filepos+2,0        ;
  591.     clc                ; set good return
  592.     ret                ;
  593.  
  594. getb:                    ; read next block
  595.     push    bx            ; save index reg
  596.     mov    bx,word ptr ihandle    ; input handle
  597.     mov    cx,bufsize        ; size to read
  598.     mov    dx,offset buffer    ; data area
  599.     mov    word ptr ibuf,dx    ; reset next char ptr
  600.     mov    ah,3fh            ; read from file
  601.     int    21h            ;
  602.     pop    bx            ; recover index reg
  603.     jc    getcx            ; none, exit
  604.     or    ax,ax            ; end of file?
  605.     jz    getcx            ; yes, return cf
  606.     mov    word ptr ilen,ax    ; save count read
  607.     jmp    short getc        ; and get next char
  608.  
  609. getcx:                    ; return with eof indication
  610.     stc                ;  of cf=1
  611.     ret
  612. getc    endp
  613.  
  614.     page
  615. ;
  616. ;    copy file to printer (or output file)
  617.  
  618. copy    proc    near
  619.     mov    ax,pages        ;                ;102
  620.     cmp    ax,2            ; 2 or less pages?        ;104
  621.     ja    copy1            ; no, need form feeds        ;104
  622.     mov    endpage,' '             ; yes, use one side only        ;104
  623. copy1:
  624.     add    ax,round_up        ; round up pages        ;104
  625.     and    ax,round_mask        ;  to multiple of four or two    ;104
  626.     shr    ax,1            ; number of two-up pages
  627.     mov    sides,ax        ;
  628.     test    flags, sw2        ; just one side?        ;105
  629.     jz    copy5            ; yes, sheets=sides        ;105
  630.     mov    right_table,offset table+ltable ; first right page    ;105
  631.     mov    left_table,offset table ; and first left page        ;105
  632.     mov    sheets,ax        ; save count            ;105
  633.     jmp    short    copy6        ;                ;105
  634.  
  635. copy5:
  636.     shr    ax,1            ; number of pages, two sides each
  637.     mov    sheets,ax        ;
  638.  
  639.     mov    ax,sides        ; get ptr for left side entries
  640.     shl    ax,1            ; number of sheets  to pages
  641.     dec    ax            ; adjust for zero indexing
  642.     mov    cx,ltable        ; get table
  643.     mul    cx            ;   pointer
  644.     add    ax,offset table     ;    for last entry
  645.     mov    left_table,ax        ; and save it
  646.  
  647.     mov    ax,offset table     ; ptr for first left side entry
  648.     mov    right_table,ax        ;  and save it
  649.  
  650. copy6:
  651.     push    sheets            ; save for second pass
  652.  
  653.     send    init,initlen        ; initialization codes
  654.  
  655.     test    flags,rws        ; ljp or downloaded font?
  656.     jz    copy6a            ;
  657.     send    initrws,initrwslen    ; if bold18 font
  658.  
  659.     mov    word ptr lmargl,'70'    ; set different margins
  660.     mov    word ptr lmargr,'59'    ;
  661.     mov    byte ptr rmargl,'1'     ;
  662.     mov    word ptr rmargl+1,'11'  ;
  663.     mov    byte ptr rmargr,'1'     ;
  664.     mov    word ptr rmargr+1,'39'  ;
  665.     jmp    short copy6b        ;
  666.  
  667. copy6a:
  668.     send    initljp,initljplen    ; if ljp standard font
  669.  
  670. copy6b:
  671.     mov    ax,sheets        ;
  672.     mov    si,offset infonr    ; tell how many sheets
  673.     call    format            ;
  674.     display info            ;
  675.  
  676.     display side1            ; say printing side 1
  677.  
  678.     call    printer         ; print first side
  679.  
  680.     pop    sheets            ; get page count back
  681.  
  682.     test    flags, sw2        ; one sided?            ;105
  683.     jnz    copy4            ; yes, all done         ;105
  684.  
  685.     cmp    pages,2         ; just one sheet needed?    ;103
  686.     jbe    copy3            ; yes, skip prompt        ;103
  687.  
  688. copy2:
  689.     display prompt            ; ask to turn paper over
  690.  
  691.     mov    ax,0c08h        ; clear console
  692.     mov    dl,0ffh         ; direct console i/o
  693.     int    21h            ;
  694.  
  695.     display side2            ; say printing side 1
  696.  
  697. copy3:
  698.     call    printer         ; print second side
  699. copy4:
  700.     cmp    endpage,ff        ; need final eject?
  701.     je    copy_ended        ; no
  702.     mov    endpage,ff        ; insure form feed
  703.     send    endpage,resetln     ; print last page, if any      ;200
  704.  
  705. copy_ended:
  706.     display ended            ; tell them we're done
  707.     ret
  708.  
  709.     page
  710. ;
  711. ;    copy left and right sides to printer one sheet at a time
  712.  
  713. printer proc    near            ; print one side of page
  714. doright:
  715.     send    right_side,right_side_len ; codes at begin of right side
  716.  
  717.     mov    si,offset right_pagenr    ; calculate page number
  718.     mov    ax,right_table        ; offset to page table entry
  719.     sub    ax,offset table     ; offset into table
  720.     sub    dx,dx            ; clear for divide
  721.     add    ax,ltable        ; start with page 1
  722.     mov    cx,ltable        ; get page number
  723.     div    cx            ;
  724.     or    ax,ax            ; page 0?
  725.     jz    doleft            ; oops
  726.     cmp    ax,pages        ; empty page?
  727.     ja    doleft            ; yes, leave it blank
  728.     test    flags,swp        ; want page number?
  729.     jz    doright1        ; no
  730.     call    format            ;
  731. doright1:
  732.     mov    dx,offset rheader    ; supplied titles
  733.     mov    cx,rheader_len        ; their length
  734.     mov    ah,40h            ; write to file
  735.     int    21h            ; via dos
  736.  
  737.     mov    si,right_table        ; right side table entry
  738.     mov    cx,word ptr 4[si]    ; get file offset
  739.     mov    dx,word ptr 2[si]    ;
  740.     mov    ax,4200h        ; position from front
  741.     mov    bx,ihandle        ;  of input file
  742.     int    21h            ;
  743.  
  744.     mov    si,right_table        ; table entry
  745.     mov    cx,word ptr 0[si]    ; length of page
  746.     sub    cx,1            ; omit formfeed
  747.     jle    doleft            ; empty
  748.     mov    dx,offset buffer    ; read data area
  749.     mov    ah,3fh            ; read from file
  750.     int    21h            ;
  751.  
  752.     call    printf            ; print this block
  753.  
  754. doleft:
  755.     send    left_side,left_side_len ; codes at begin of page
  756.  
  757.     mov    si,offset left_pagenr    ; determine page number
  758.     mov    ax,left_table        ; offset to page table entry
  759.     sub    ax,offset table     ; offset into table
  760.     sub    dx,dx            ; clear for divide
  761.     add    ax,ltable        ; start with page 1
  762.     mov    cx,ltable        ; get page number
  763.     div    cx            ;
  764.     or    ax,ax            ; page 0?
  765.     jz    doleft2         ; oops
  766.     cmp    ax,pages        ; is this page empty?
  767.     ja    doleft2         ; yes, don't over-write header
  768.  
  769. doleft0:
  770.     test    flags,swp        ; want page number?
  771.     jz    doleft1         ; no, skip next
  772.     call    format            ; yes, make it readable
  773.  
  774. doleft1:
  775.     mov    dx,offset lheader    ; supplied titles
  776.     mov    cx,lheader_len        ; their length
  777.     mov    ah,40h            ; write to file
  778.     int    21h            ; via dos
  779.  
  780.     mov    si,left_table        ; left side table entry
  781.     mov    cx,word ptr 4[si]    ; get file offset
  782.     mov    dx,word ptr 2[si]    ;
  783.     mov    ax,4200h        ; position from front
  784.     mov    bx,ihandle        ;  of input file
  785.     int    21h            ;
  786.  
  787.     mov    si,left_table        ; table entry
  788.     mov    cx,word ptr 0[si]    ; length of page
  789.     sub    cx,1            ; omit ending formfeed
  790.     jle    doleft2         ; empty
  791.     mov    dx,offset buffer    ; read data area
  792.     mov    ah,3fh            ; read from file
  793.     int    21h            ;
  794.  
  795.     call    printf            ; copy file to printer
  796.  
  797. doleft2:
  798.     send    endpage,endlen        ; eject at end of left page
  799.  
  800.     add    right_table,ltable+ltable ; next right table entry
  801.     test    flags,sw2        ; one sided?
  802.     jnz    doleft3         ; yes,
  803.     sub    left_table,ltable+ltable  ; next left side table entry
  804.     jmp    short doleft4        ;
  805.  
  806. doleft3:
  807.     add    left_table,ltable+ltable ; next one-sided left side page
  808. doleft4:
  809.     sub    sheets,1        ; decr sheet count
  810.     jle    printer_exit        ; no more sheets
  811.     jmp    doright         ; do next page
  812.  
  813. printer_exit:                ;
  814.     ret                ; done, exit
  815.  
  816.     page
  817. ;
  818. ;    copy file's page to printer with tabbing
  819.  
  820. flen    dw    0            ; length of file's page
  821.  
  822. printf:
  823.     mov    si,offset buffer    ; page's file data
  824.     mov    flen,ax         ; set length
  825. printf2:
  826.     mov    di,offset pline     ; to a single print line
  827.     mov    bx,0            ; relative column
  828. printf3:
  829.     lodsb                ; get next char
  830.     dec    flen            ; decr length remaining
  831.     cmp    al,tab            ; is it a tab char?
  832.     jne    printf4         ; no, check for new line
  833.     mov    cx,bx            ; current column
  834.     add    cx,8            ; round up
  835.     and    cx,0fff8h        ;  to tab column
  836.     sub    cx,bx            ; get number of
  837.     add    bx,cx            ;  blank chars
  838.     jcxz    printf8         ;
  839.     mov    al,' '                  ; move in
  840.     rep    stosb            ;  the blanks
  841. printf8:
  842.     jmp    printf6         ;
  843.  
  844. printf4:
  845.     stosb                ; copy next char
  846.     inc    bx            ; bump column
  847.     cmp    al,lf            ; new line?
  848.     je    printf5         ; yes, print it now
  849.     cmp    al,cr            ; overlap line?
  850.     jne    printf6         ; no, continue
  851.     mov    bx,0            ; yes, reset tab column
  852.  
  853. printf6:
  854.     cmp    flen,0            ; any length remaining?
  855.     jne    printf3         ; yes, get next char
  856.     mov    al,lf            ; append final lf
  857.     stosb                ;
  858.  
  859. printf5:
  860.     mov    dx,offset pline     ; start of line
  861.     mov    cx,di            ;  less end of line
  862.     sub    cx,dx            ;   as length of line
  863.     jle    printf9         ; null line?
  864.     send    pline,cx        ; no, send it to printer
  865. printf9:
  866.     cmp    flen,0            ; all done?
  867.     jg    printf2         ; no, do another line
  868.     ret                ; resume
  869. printer endp
  870.  
  871. copy    endp
  872.  
  873. ljbook    endp
  874.  
  875.     page
  876. ;
  877. ;    convert a binary number to ascii
  878.  
  879.     public    format
  880. format    proc    near            ; format a block number
  881.     sub    dx,dx            ; entry for one word in ax only
  882. formatd:push    ax
  883.     push    bx            ; value in dx:ax
  884.     push    cx            ; offset to target
  885.     push    dx            ;
  886.     push    di            ;
  887.  
  888.     mov    bx,si            ; save target offset
  889.     mov    cx,6            ; clear target
  890. form0:    mov    byte ptr [si],' '       ;
  891.     inc    si            ;
  892.     loop    form0            ;
  893.  
  894.     mov    cx,4            ; four times
  895.     sub    di,di            ; divisor offset
  896.     mov    si,bx            ; restore target ptr
  897. form1:    or    ax,ax            ; it is zero?
  898.     jnz    form10            ;
  899.     or    dx,dx            ;
  900.     jz    form2            ;
  901. form10: div    tenk[di]        ;
  902.     aam                ; make al into bcd
  903. form2:    or    ax,'00'                 ; and to ascii
  904.     xchg    al,ah            ;
  905.     or    byte ptr [si],al    ;
  906.     mov    byte ptr [si]+1,ah    ;
  907.     inc    si            ; next digit
  908.     add    di,2            ; next divisor
  909.     mov    ax,dx            ; copy remainder
  910.     sub    dx,dx            ; and clear hi-word
  911.     loop    form1            ;
  912.  
  913.     aam                ; make al into bcd
  914.     or    ax,'00'                 ; and to ascii
  915.     xchg    al,ah            ;
  916.     mov    byte ptr [si]+1,ah    ;
  917.     mov    cx,5            ; suppress leading zeros
  918.     mov    si,bx            ; get target offset back
  919. form3:    cmp    byte ptr [si],'0'       ;
  920.     jne    form4            ;
  921.     mov    byte ptr [si],' '       ;
  922.     inc    si            ;
  923.     loop    form3            ;
  924.  
  925. form4:    pop    di            ; restore work regs
  926.     pop    dx            ;
  927.     pop    cx            ;
  928.     pop    bx            ;
  929.     pop    ax            ;
  930.     ret                ; resume
  931.  
  932. tenk    dw    10000,1000,100,10    ; for converting numbers
  933. format    endp
  934.  
  935.     page
  936. ;
  937. ;    set up optional page headings
  938.  
  939. headers proc    near
  940.     test    flags,swf+swd+swp+swt    ; any header options?
  941.     jz    header_exit        ; no, that was easy
  942.     test    flags,swf        ; want file name?
  943.     jz    header2         ; no
  944.     mov    cx,40            ;
  945.     mov    si,offset ifile     ; yes, copy filename
  946.     mov    di,offset right_fname    ;
  947. headera:
  948.     lodsb                ; copy up to end of name
  949.     cmp    al,0            ;
  950.     je    headerb         ;
  951.     stosb                ;
  952.     loop    headera         ;
  953. headerb:
  954.     mov    cx,40            ;
  955.     std                ; backwards
  956.     mov    si,offset ifile+39    ;  from end of filename
  957.     mov    di,offset left_fname    ;   to end of left filename area
  958. header1:
  959.     lodsb                ;
  960.     cmp    al,0            ; found end of name?
  961.     loope    header1         ; not yet
  962.     inc    cx            ;
  963.     inc    si            ;
  964.     rep    movsb            ; yes, copy it
  965. header2:
  966.     cld                ; restore direction
  967.     test    flags,swp        ; want page numbering?
  968.     jz    header4         ; no,
  969.     mov    si,offset page_const    ; yes, copy constant
  970.     mov    di,offset left_page    ;  'page' to left side
  971.     mov    cx,5            ;
  972.     rep    movsb            ;
  973.     mov    si,offset page_const    ;
  974.     mov    di,offset right_page    ;
  975.     mov    cx,5            ;
  976.     rep    movsb            ;
  977. header4:
  978.     test    flags,swd        ; want date in title?
  979.     jz    header5         ; no, skip next
  980.     mov    di,offset left_date    ; format today's date
  981.     call    getdate         ;  in left side titles
  982.     mov    di,offset left_time    ; format today's time
  983.     call    gettime         ;  in left side titles
  984.     mov    di,offset right_date    ; format today's date
  985.     call    getdate         ;  in right side titles
  986.     mov    di,offset right_time    ; format today's time
  987.     call    gettime         ;  in right side titles
  988. header5:
  989. header_exit:
  990.     ret                ; resume
  991. headers endp
  992.  
  993.     page
  994. ;
  995. ;    get and format current date
  996. ;
  997. ;    input: DI points to target area
  998.  
  999. getdate proc    near
  1000.     mov    ah,2ah            ; get date
  1001.     int    21h            ;
  1002.     push    cx            ; save year
  1003.     push    dx            ; save day
  1004.  
  1005.     mov    bl,dh            ; get month
  1006.     sub    bh,bh            ; form index
  1007.     shl    bx,1            ;  into month
  1008.     shl    bx,1            ;   name list
  1009.     lea    si,offset months-4[bx]    ; copy month name
  1010.     mov    cx,4            ;
  1011.     rep    movsb            ;
  1012.     mov    al,' '                  ; add space
  1013.     stosb                ;
  1014.  
  1015.     pop    dx            ; recover day
  1016.     mov    al,dl            ; get day
  1017.     aam                ;
  1018.     xchg    al,ah            ;
  1019.     or    ax,'00'                 ;
  1020.     stosw                ;
  1021.     mov    ax,' ,'                 ; add delimiter
  1022.     stosw                ;
  1023.     mov    ax,'91'                 ; add century
  1024.     stosw
  1025.  
  1026.     pop    ax            ; get year(19xx)
  1027.     sub    ax,1900         ;
  1028.     aam                ;
  1029.     xchg    al,ah            ;
  1030.     or    ax,'00'                 ;
  1031.     stosw                ;
  1032.     ret                ; return
  1033. getdate endp
  1034.  
  1035.     page
  1036. ;
  1037. ;    get current time
  1038. ;
  1039. ;    input: DI points to target area
  1040.  
  1041. gettime proc    near
  1042.     mov    ah,2ch            ; dos time function
  1043.     int    21h            ;
  1044.     mov    al,ch            ; get hours
  1045.     aam                ;
  1046.     xchg    al,ah            ;
  1047.     or    ax,'00'                 ;
  1048.     stosw                ;
  1049.     mov    al,':'                  ; add delimiter
  1050.     stosb                ;
  1051.     mov    al,cl            ; get minutes
  1052.     aam                ;
  1053.     xchg    al,ah            ;
  1054.     or    ax,'00'                 ;
  1055.     stosw                ;
  1056.     ret                ; return
  1057. gettime endp
  1058.  
  1059.     page
  1060. ;
  1061. ;    tables and dynamic data areas
  1062.  
  1063.     even
  1064. pline    label    byte            ; each print line
  1065.  
  1066. bufsize equ    18*1024         ; input file buffer size
  1067. buffer    equ    pline+256        ;
  1068.  
  1069. lstack    equ    buffer + bufsize + 512    ; local stack
  1070.  
  1071. ltable    equ    6            ; size of each entry
  1072. table    equ    lstack+2        ; page/offset table
  1073.                     ;  0,2     page size in bytes
  1074.                     ;  2,4     file offset to top of page
  1075.  
  1076. pgmsize equ    lstack-cseg+512     ; paragraphs in module
  1077.  
  1078. cseg    ends
  1079.     end    ljbook
  1080.